﻿#pragma once

#include "MaterialGraph/Node/MaterialGraphNodeViewModel.h"
#include "MaterialGraph/OperationNode/MaterialOperationNodeModel.h"
#include "MaterialOperationNodeViewModel.m.h"

RCLASS()
class RMaterialOperationNodeViewModel : public RMaterialGraphNodeViewModel
{
    ROBJECT

public:
    virtual void BindModel(
        TSharedObjectPtr<RMaterialGraphNodeModel> InModel
        , TSharedObjectPtr<RMaterialGraphViewModel> InGraph
        ) ;

    virtual float GetNodeWidth() const  override{ return 200.0f; }
    virtual int64_t GetLineNum() const override;
    virtual CString GetName() const override { return GetOperationName(); };

    virtual CString GetInputPinName(int64_t Index) const override;
    virtual CString GetOutputPinName(int64_t Index) const override{ return U"结果"; }

    CString GetOperationName() const;

    bool IsClampEnable() const;
    void EnableClamp(bool bEnable);

    TSharedObjectPtr<RMaterialGraphPinViewModel> GetFirstInputPinViewModel() const;

    TSharedObjectPtr<RMaterialGraphPinViewModel> GetSecondInputPinViewModel() const;

    TSharedObjectPtr<RMaterialGraphPinViewModel> GetThirdInputPinViewModel() const;

    TSharedObjectPtr<RMaterialGraphPinViewModel> GetOutputPinViewModel() const;

    bool IsInputBVisible() const;

    bool IsInputCVisible() const;

    EMaterialOperationType GetOperationType() const;

    const float ColumnLineHeight=20.0f;
    const float PopupMenuHorizontalSpacing=10.0f;
    const float PopupMenuVerticalSpacing=5.0f;
    const float PopupMenuPadding=5.0f;

    float GetPopupMenuWidth() const;
    float GetPopupMenuHeight() const;

    int64_t GetPopupMenuColumnNum() const;
    CString GetPopupMenuColumnName(int64_t ColumnIndex) const;
    float GetPopupMenuColumnWidth(int64_t ColumnIndex) const;
    int64_t GetPopupMenuLineNum(int64_t ColumnIndex) const;
    CString GetPopupMenuItemName(int64_t ColumnIndex,int64_t LineIndex ) const;
    void UseOperationTypeInMenu(int64_t ColumnIndex,int64_t LineIndex);

protected:
    TWeakObjectPtr<RMaterialOperationNodeModel> OperationModel;

    struct SPopupMenuItem
    {
        EMaterialOperationType OperationType;
    };

    struct SPopupMenuColumn
    {
        CString Name;
        float Width=100.0f;
        TVector<SPopupMenuItem> Items;
    };

    struct SPopupMenu
    {
        SVec2 Size;
        TVector<SPopupMenuColumn> Columns;
    };

    SPopupMenu PopupMenu;

    struct SOperationTypeData
    {
        SOperationTypeData(TVector<CString> InDisplayNames)
        {
            DisplayName=InDisplayNames[0];
            InputADisplayName=InDisplayNames[1];
            if(InDisplayNames.Num()>2)
            {
                InputBDisplayName=InDisplayNames[2];
            }

            if(InDisplayNames.Num()>3)
            {
                InputCDisplayName=InDisplayNames[3];
            }
        }

        CString DisplayName;

        CString InputADisplayName;
        CString InputBDisplayName;
        CString InputCDisplayName;
    };

    TMap<EMaterialOperationType, SOperationTypeData> OperationTypeData;

};